package structs;

import java.util.ArrayList;

import interfaces.ICard;
import interfaces.IPlayer;

public class CardStrategy 
{
	private Game game;
	private ICard [] currentCardsPlayed;
	private Deck deck;
	private int turn;
	private int aiPosition;
	private int teamMatePosition;
	private IPlayer ai;
	private IPlayer teamMate;
	private ArrayList<ICard> currentHand = new ArrayList<ICard>();
	private CardProbability cardProb;


	public ICard hand1;
	public ICard hand2;
	public ICard hand3;


	public CardStrategy(Game game, CardProbability cardProb){
		this.game = game;
		this.ai = this.game.getAIPlayer();
		this.teamMate = this.game.getTeamPlayer();
		this.cardProb = cardProb;
	}

	public void updateCardStrategy()
	{
		this.currentCardsPlayed = this.game.getCurrentCardsPlayed();
		this.turn = this.game.getCurrentHandTurn();
		this.aiPosition = this.game.getAIPosition();
		this.teamMatePosition = this.game.getTeamPosition();
		this.currentHand = this.ai.getCurrentHand();
		this.deck = this.game.getDeck();

		if(this.game.getRoundNumber()<=7)
		{
			this.currentHand = this.ai.getCurrentHand();
			this.hand1 = this.currentHand.get(0);
			this.hand2 = this.currentHand.get(1);
			this.hand3 = this.currentHand.get(2);
		}
		
		else if(this.game.getRoundNumber()==9)
		{
			this.hand1 = this.currentHand.get(0);
			this.hand2 = this.currentHand.get(1);
		}
		
		else
		{
			this.hand1 = this.currentHand.get(0);
		}
		
		
	}

	public ICard highestNoneLife()
	{
		for(int j=this.currentHand.size()-1; j>0;j--)
		{
			if(!this.currentHand.get(j).getSuit().equalsIgnoreCase(deck.getLife().getSuit()))
			{
				if(this.currentHand.get(j).getPoints() > 0)
				{
					if(this.currentHand.get(j).getNumber()==this.currentHand.get(j-1).getNumber())
					{
						double prob1 = cardProb.getProbHigherHand(j-1);
						double prob2 = cardProb.getProbHigherHand(j);

						if(prob1 >= prob2)
						{
							return this.currentHand.get(j-1);
						}

						else
						{
							return this.currentHand.get(j);
						}
					}
					return this.currentHand.get(j);
				}
			}
		}
		return this.hand1;
	}

	public ICard highestSuitLife() {
		ICard card = cardThatIsWinning();

		if(card.getSuit().equalsIgnoreCase(deck.getLife().getSuit()))
		{
			return lowestWinningLife();
		}

		for(int j=this.currentHand.size()-1; j>=0;j--)
		{
			if(this.currentHand.get(j).getSuit().equalsIgnoreCase(card.getSuit())
					&& ((this.currentHand.get(j).getPoints() > card.getPoints()) 
							|| (((this.currentHand.get(j).getPoints()== 0) && (card.getPoints()==0))
									&& (this.currentHand.get(j).getNumber() > card.getNumber()))))
			{
				return this.currentHand.get(j);
			}
		}

		return lowestWinningLife();
	}

	public ICard lowestSuitNoneLife() {
		ICard card = cardThatIsWinning();

		if(card.getSuit().equalsIgnoreCase(deck.getLife().getSuit()))
		{
			if(this.hand1.getPoints()>=10)
			{
				return lowestLife();
			}

			else
			{
				return this.hand1;
			}
		}

		return lowestWinningSuit();
	}

	public ICard lowestWinningLife() 
	{
		ICard card = cardThatIsWinning();

		if(card.getSuit().equalsIgnoreCase(deck.getLife().getSuit()))
		{
			for(int j=0; j<this.currentHand.size();j++)
			{	
				if((this.currentHand.get(j).getSuit().equalsIgnoreCase(deck.getLife().getSuit()))
						&& ((this.currentHand.get(j).getPoints() > card.getPoints())
								|| (((this.currentHand.get(j).getPoints() == 0) && (card.getPoints() ==0))
										&& (this.currentHand.get(j).getNumber() > card.getNumber()))))
				{
					return this.currentHand.get(j);
				}
			}
		}

		for(int j=0; j<this.currentHand.size();j++)
		{	
			if(this.currentHand.get(j).getSuit().equalsIgnoreCase(deck.getLife().getSuit()))
			{
				return this.currentHand.get(j);
			}
		}

		return this.hand1;
	}

	public ICard lowestLife() 
	{

		for(int j=0; j<this.currentHand.size();j++)
		{	
			if((this.currentHand.get(j).getSuit().equalsIgnoreCase(deck.getLife().getSuit()))
					&& (this.currentHand.get(j).getPoints() <=4))
			{
				return this.currentHand.get(j);
			}
		}

		return this.hand1;
	}


	public ICard cardThatIsWinning(){
		ICard max = this.currentCardsPlayed[0];
		String playSuit = this.currentCardsPlayed[0].getSuit();


		for(int i = 1 ; i < this.turn; i++){
			if(	
					//Max no es vida y currentCardsPlayed es vida
					(!max.getSuit().equalsIgnoreCase(this.deck.getLife().getSuit()) 
							&& this.currentCardsPlayed[i].getSuit().equalsIgnoreCase(this.deck.getLife().getSuit())) ||
					//Max es vida, currentCardsPlayed es vida, currentCardsPlayed tiene mas puntos
					(max.getSuit().equalsIgnoreCase(this.deck.getLife().getSuit()) 
							&& this.currentCardsPlayed[i].getSuit().equalsIgnoreCase(this.deck.getLife().getSuit()) 
							&& max.getPoints() < this.currentCardsPlayed[i].getPoints()) ||
					//Max es vida, currentCardsPlayed es vida, currentCardsPlayed vale 0 pntos, max vale 0 pnts, currentCardsPlayed tiene un numero mas grande q max
					(max.getSuit().equalsIgnoreCase(this.deck.getLife().getSuit()) 
							&& this.currentCardsPlayed[i].getSuit().equalsIgnoreCase(this.deck.getLife().getSuit()) 
							&& this.currentCardsPlayed[i].getPoints() == 0 
							&& max.getPoints() == 0 
							&& this.currentCardsPlayed[i].getNumber() > max.getNumber()) ||
					//currentCardsPlayed es del Playsuit, max es del playSuit, currentCardsPlayed tiene mas puntos que max
					(this.currentCardsPlayed[i].getSuit().equalsIgnoreCase(playSuit) 
							&& max.getSuit().equalsIgnoreCase(playSuit)
							&& max.getPoints() < this.currentCardsPlayed[i].getPoints()) ||
					//currentCardsPlayed es del playSuit, max es del playSuit, ambos tienes 0 pnts, currentCardsPlayed tiene un numero mas grande q max
					(this.currentCardsPlayed[i].getSuit().equalsIgnoreCase(playSuit) 
							&& max.getSuit().equalsIgnoreCase(playSuit)
							&& this.currentCardsPlayed[i].getPoints() == 0 
							&& max.getPoints() == 0 
							&& this.currentCardsPlayed[i].getNumber() > max.getNumber())
				){

				max = this.currentCardsPlayed[i];
			}
		}
		return max;
	}

	public int currentCardsPlayedPoints()
	{
		int currentPoints = 0;

		for(int i=0; i< this.turn; i++)
		{
			currentPoints += this.currentCardsPlayed[i].getPoints();
		}
		//Points in the hand being played
		return currentPoints;
	}

	public ICard lowestCardWithHighProbOfLossing() {
		double maxProb = 0.0;
		int index = 0;

		for(int j=0; j<this.currentHand.size();j++)
		{
			if((this.currentHand.get(j).getPoints()) == 0 && (!this.currentHand.get(j).getSuit().equalsIgnoreCase(deck.getLife().getSuit())))
			{
				if(this.cardProb.getProbHigherHand(j) >= maxProb)
				{
					maxProb = this.cardProb.getProbHigherHand(j);
					index = j;
				}
			}
		}

		if(this.hand1.getPoints() >=10) 
		{
			if(this.lowestLife().getPoints() >= 10)
			{
				//FIXME
				if(this.ai.getCurrentHand().size()>1 && this.hand2.getSuit().equalsIgnoreCase(deck.getLife().getSuit()))
				{
					return this.hand1;
				}

				else
				{
					double prob1 = cardProb.getProbHigherHand(0);
					double prob2 = cardProb.getProbHigherHand(1);

					if(prob1 >= prob2)
					{
						return this.hand1;
					}

					else
					{
						if(this.ai.getCurrentHand().size()>1)
						{
						return this.hand2;
						}
						else
						{
							return this.hand1;
						}
					}
				}
			}

			else
			{
				return lowestLife();
			}
		}

		return this.currentHand.get(index);
	}

	public ICard lowestWinningSuit()
	{
		ICard card = cardThatIsWinning();

		for(int j=0; j<this.currentHand.size();j++)
		{
			if(((this.currentHand.get(j).getSuit().equalsIgnoreCase(card.getSuit()))
					&& (this.currentHand.get(j).getPoints() <=4))
					&& ((this.currentHand.get(j).getPoints() > card.getPoints()) 
							|| (((this.currentHand.get(j).getPoints()== 0) && (card.getPoints()==0))
									&& (this.currentHand.get(j).getNumber() > card.getNumber()))))
			{
				return this.currentHand.get(j);
			}
		}

		if(this.hand1.getPoints()>=10)
		{
			lowestLife();
		}

		return this.hand1;

	}

	public ICard highestWinningSuit() {
		ICard card = cardThatIsWinning();

		if(card.getSuit().equalsIgnoreCase(deck.getLife().getSuit())
				&& card.getPoints()<=4)	
		{
			if (this.hand1.getPoints()>=10)
			{
				lowestLife();
			}

			else
			{
				return this.hand1;
			}
		}

		for(int j=this.currentHand.size()-1; j>=0;j--)
		{
			if(this.currentHand.get(j).getSuit().equalsIgnoreCase(card.getSuit())
					&& ((this.currentHand.get(j).getPoints() > card.getPoints()) 
							|| (((this.currentHand.get(j).getPoints()== 0) && (card.getPoints()==0))
									&& (this.currentHand.get(j).getNumber() > card.getNumber()))))
			{
				return this.currentHand.get(j);
			}
		}

		if(this.hand1.getPoints() >= 10)
		{
			return lowestLife();
		}

		return this.hand1;
	}

	
	//Cosas para considerar: quedan 12 cartas. Yo conozco 3 y desconozco 9.
	//Si tengo 3 vida, y no tengo el 1 vida o no lo han tirado,  tirarlo antes de que me lo coman
	//
	
	public ICard lastFirstTurn(){
		//Check turn (1 or 2);
		//Check for lowest life in hand
		//If no lives low, try to check for suit that doesn't have higher cards
		//Check to see team players hand and/or opponents

		ICard temp = null;

		if(this.game.getAIPosition() == 1){
			temp = this.lowestLife();

			if(!temp.getSuit().equalsIgnoreCase(this.game.getDeck().getLife().getSuit()) || temp.getPoints() > 3 ){
				//Card wasn't life or was to high
				//Choose card that suit doesn't have "Briscas"
				temp = this.getCardSuitWithNoBriscas();
			}
		}
		else if(this.game.getAIPosition() == 2){
			//Check to see card that was played
			ICard firstCard = this.currentCardsPlayed[0];

			if(firstCard.getPoints() > 4){
				//Person played Brisca. Try to win with low life
				temp = this.lowestLife();

				if(!temp.getSuit().equalsIgnoreCase(this.game.getDeck().getLife().getSuit()) || temp.getPoints() > 3 ){
					//Card wasn't life or was too high
					//Choose card that suit doesn't have "Briscas"
					temp = this.getCardSuitWithNoBriscas();
				}
			}
			//Card is of low importance
			else{
				temp = this.lowestLife();
			}
		}

		if(temp == null){
			temp = this.hand1;
		}

		return temp;
	}

	public ICard lastTurn(BooleanStrategy bs){		
		ICard temp = null;

		if(bs.areWeWinning()){
			//Si estamos ganando, tirar brisca q no sea vida
			if(this.game.getAIPosition() == 4){
				temp = this.highestNoneLife();
			}
			else if(this.game.getAIPosition() == 3){
				//Check for chances of winning/lossing
				temp = this.highestNoneLife();
			}

		}
		else if(bs.doWeNeedToWin()){
			//Si hay muchos puntos, y no estamos ganando, tratar de matar con vida o subir
			if(this.game.getAIPosition() == 4){
				//Tratar de subir el suit o tirar vida bajita
				temp = this.highestWinningSuit();
			}
			else if(this.game.getAIPosition() == 3){
				//Check for chances of winning/lossing
				temp = this.highestWinningSuit();
			}
		}

		//Tirar basura

		if(temp == null){
			temp = this.hand1;
		}

		return temp;	
	}

	public boolean hasHigherCards(ICard card){
		
		Deck deck = this.game.getDeck();
		
		ArrayList<ICard> cards = deck.getCards(card.getSuit());
		
		boolean has = false;
		
		for(int i = 0; i < cards.size(); i++){
			
			if(card.getPoints() < cards.get(i).getPoints()){
				has = true;
				break;
			}
			
		}
		
		return has;
	}
	
	public ICard getCardSuitWithNoBriscas(){
		
		ICard temp = null;
		
		for(int j=0; j<this.currentHand.size();j++){
			ArrayList<ICard> cards = this.game.getDeck().getCards(this.currentHand.get(j).getSuit());
			
			boolean hasBriscas = false;
			
			for(int i = 0; i < cards.size(); i++){
				if(cards.get(i).getPoints() > 3 ){
					hasBriscas = true;
					break;
				}
			}
			
			if(!hasBriscas && temp == null){
				temp = this.currentHand.get(j);
			}
			else if(!hasBriscas && temp.getPoints() >= this.currentHand.get(j).getPoints()){
				temp = this.currentHand.get(j);
			}

		}

		if(temp == null){
			temp = this.hand1;
		}
		
		return temp;
	}
	
	public ICard lowestCard()
	{
		if(this.hand1.getPoints() >=10)
		{
			return lowestLife();
		}

		else
		{
			return this.hand1;
		}
	}
}